package com.ht.api.handler;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.ht.api.bean.AjaxResult;
import com.ht.api.handler.auth.ICheck;
import com.ht.api.init.ApiInitializer;
import com.ht.api.util.IpUtils;

import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

/**
 * 接口调用鉴权
 * @author asq
 * @createTime 2024年12月21日 11:01:18
 */
@Slf4j
@Component
public class AuthHandler implements HandlerInterceptor {
	@Resource
	private ICheck checkLogin;
	@Resource
	private ICheck checkAuthorize;
	
	@Override
	public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object obj, Exception e)
			throws Exception {
	}

	@Override
	public void postHandle(HttpServletRequest req, HttpServletResponse res, Object obj, ModelAndView mav)
			throws Exception {
	}

	@Override
	public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object obj) throws Exception {
		//openApi不需要拦截
		String openApi = req.getRequestURI();
		if (openApi.endsWith("/")) {
			openApi = openApi.substring(0, openApi.length() - 1);
		}
		if (ApiInitializer.openApis.contains(openApi)) {
			log.info("访问openApi，跳过拦截：{}", openApi);
			return true;
		}
		
		//鉴权
		log.info("[鉴权]原始串：" + getUrl(req));
		AjaxResult result = auth(req, res);

		//鉴权通过，则允许调用接口；否则直接返回json
		if (result == null || result.isSuccess()) {
			return true;
		} else {
			//处理跨域问题
			res.setHeader("Access-Control-Allow-Origin", "*");

			//返回拒绝的json
			log.info("[鉴权]IP[{}]不通过：{}", IpUtils.getIpAddr(), result.getMsg());
			PrintWriter writer = null;
			res.setCharacterEncoding("UTF-8");
			res.setContentType("text/json; charset=utf-8");
			try {
				writer = res.getWriter();
				writer.print(result.toJson());
				writer.flush();
			} catch (IOException e) {
				log.error("接口鉴权写入response失败！", e);
			} finally {
				if (writer != null) writer.close();
			}
			return false;
		}
	}

	/**
	 * 接口鉴权
	 * @param req
	 * @return
	 */
	private AjaxResult auth(HttpServletRequest req, HttpServletResponse res) {
		List<ICheck> checkList = new ArrayList<>();
		checkList.add(checkLogin);//检查登陆
		checkList.add(checkAuthorize);//检查权限
		for (ICheck checkImpl : checkList) {
			AjaxResult result = checkImpl.check(req, res);
			if (!result.isSuccess()) { return result; }
		}
		return AjaxResult.success();
	}

	/**
	 * 获取访问的完整url
	 * @param req
	 * @return
	 */
	private String getUrl(HttpServletRequest req) {
		StringBuilder url = new StringBuilder();
		url.append(req.getRequestURL().toString());
		String queryString = req.getQueryString();
		if (queryString != null && !queryString.isEmpty()) {
			try {
				queryString = URLDecoder.decode(queryString, "utf-8");
			} catch (UnsupportedEncodingException e) {
			}
			url.append("?");
			url.append(queryString);
		}

		//附加上post里面不重复的参数，方便日志调试
		Map<String, String[]> map = req.getParameterMap();
		String split = "&";
		for (String key : map.keySet()) {
			String str = split + queryString;
			if (str.indexOf("?" + key + "=") == -1 && str.indexOf("&" + key + "=") == -1) {
				//排除图片参数
				if ("file,imgs,headimg".indexOf(key) == -1) {
					url.append(split);
					url.append(key);
					url.append("=");
					url.append(req.getParameter(key));
				}
			}
		}

		return url.toString().replaceFirst("&", "?");
	}
}